{
 "cells": [
  {
   "cell_type": "code",
   "id": "initial_id",
   "metadata": {
    "collapsed": true,
    "ExecuteTime": {
     "end_time": "2025-06-26T03:30:37.478033Z",
     "start_time": "2025-06-26T03:30:37.460220Z"
    }
   },
   "source": [
    "#6.2 图像卷积\n",
    "import torch\n",
    "from torch import nn\n",
    "from d2l import torch as d2l\n",
    "\n",
    "\n",
    "def corr2d(X, K):  #@save\n",
    "\t\"\"\"计算二维互相关运算\"\"\"\n",
    "\th, w = K.shape\n",
    "\tY = torch.zeros(X.shape[0] - h + 1, X.shape[1] - w + 1)\n",
    "\tfor i in range(Y.shape[0]):\n",
    "\t\tfor j in range(Y.shape[1]):\n",
    "\t\t\tY[i, j] = (X[i:i + h, j:j + w] * K).sum()  #卷积运算\n",
    "\treturn Y"
   ],
   "outputs": [],
   "execution_count": 8
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-26T03:30:37.494172Z",
     "start_time": "2025-06-26T03:30:37.483699Z"
    }
   },
   "cell_type": "code",
   "source": [
    "X = torch.tensor([[0.0, 1.0, 2.0], [3.0, 4.0, 5.0], [6.0, 7.0, 8.0]])\n",
    "K = torch.tensor([[0.0, 1.0], [2.0, 3.0]])\n",
    "corr2d(X, K)"
   ],
   "id": "b1de2b7b9d759fdc",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[19., 25.],\n",
       "        [37., 43.]])"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 9
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-26T03:30:46.917888Z",
     "start_time": "2025-06-26T03:30:46.909408Z"
    }
   },
   "cell_type": "code",
   "source": [
    "class Conv2D(nn.Module):\n",
    "\tdef __init__(self, kernel_size):\n",
    "\t\tsuper(Conv2D, self).__init__()\n",
    "\t\tself.weight = nn.Parameter(torch.randn(kernel_size))\n",
    "\t\tself.bias = nn.Parameter(torch.zeros(1))\n",
    "\n",
    "\tdef forward(self, X):\n",
    "\t\treturn corr2d(X, self.weight) + self.bias\n",
    "\n",
    "\n",
    "X = torch.ones((6, 8))\n",
    "X[:, 2:6] = 0\n",
    "X"
   ],
   "id": "4df1e7b2b98de440",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[1., 1., 0., 0., 0., 0., 1., 1.],\n",
       "        [1., 1., 0., 0., 0., 0., 1., 1.],\n",
       "        [1., 1., 0., 0., 0., 0., 1., 1.],\n",
       "        [1., 1., 0., 0., 0., 0., 1., 1.],\n",
       "        [1., 1., 0., 0., 0., 0., 1., 1.],\n",
       "        [1., 1., 0., 0., 0., 0., 1., 1.]])"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 11
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-26T03:31:07.257380Z",
     "start_time": "2025-06-26T03:31:07.242919Z"
    }
   },
   "cell_type": "code",
   "source": "K = torch.tensor([[1.0, -1.0]])  #定义边缘检测卷积核",
   "id": "749608785af8288e",
   "outputs": [],
   "execution_count": 12
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-26T03:31:20.407079Z",
     "start_time": "2025-06-26T03:31:20.392738Z"
    }
   },
   "cell_type": "code",
   "source": [
    "Y = corr2d(X, K)\n",
    "Y"
   ],
   "id": "605a01ac43c75f65",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[ 0.,  1.,  0.,  0.,  0., -1.,  0.],\n",
       "        [ 0.,  1.,  0.,  0.,  0., -1.,  0.],\n",
       "        [ 0.,  1.,  0.,  0.,  0., -1.,  0.],\n",
       "        [ 0.,  1.,  0.,  0.,  0., -1.,  0.],\n",
       "        [ 0.,  1.,  0.,  0.,  0., -1.,  0.],\n",
       "        [ 0.,  1.,  0.,  0.,  0., -1.,  0.]])"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 13
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-26T03:32:11.714673Z",
     "start_time": "2025-06-26T03:32:11.707684Z"
    }
   },
   "cell_type": "code",
   "source": "corr2d(X.t(), K)  #智能检测水平边缘",
   "id": "42a3397fe25afcec",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[0., 0., 0., 0., 0.],\n",
       "        [0., 0., 0., 0., 0.],\n",
       "        [0., 0., 0., 0., 0.],\n",
       "        [0., 0., 0., 0., 0.],\n",
       "        [0., 0., 0., 0., 0.],\n",
       "        [0., 0., 0., 0., 0.],\n",
       "        [0., 0., 0., 0., 0.],\n",
       "        [0., 0., 0., 0., 0.]])"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 15
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-26T03:39:08.947651Z",
     "start_time": "2025-06-26T03:39:08.907711Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 构造一个二维卷积层，它具有1个输出通道和形状为（1，2）的卷积核\n",
    "conv2d = nn.Conv2d(1, 1, kernel_size=(1, 2), bias=False)\n",
    "\n",
    "X = X.reshape((1, 1, 6, 8)) #输入图像\n",
    "Y = Y.reshape((1, 1, 6, 7)) #上面的真实的卷积后结果\n",
    "lr = 3e-2\n",
    "\n",
    "for i in range(100):\n",
    "\tY_hat = conv2d(X)\n",
    "\tl = (Y_hat - Y) ** 2\n",
    "\tconv2d.zero_grad()\n",
    "\tl.sum().backward()\n",
    "\tconv2d.weight.data[:] -= lr * conv2d.weight.grad\n",
    "\tif (i+1)%2 == 0:\n",
    "\t\tprint(f'epoch {i+1},loss:{l.sum()}')"
   ],
   "id": "cdef25048f5c646e",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch 2,loss:6.813455581665039\n",
      "epoch 4,loss:1.7824981212615967\n",
      "epoch 6,loss:0.560947835445404\n",
      "epoch 8,loss:0.201383575797081\n",
      "epoch 10,loss:0.0777251124382019\n",
      "epoch 12,loss:0.031037313863635063\n",
      "epoch 14,loss:0.012578814290463924\n",
      "epoch 16,loss:0.005129768513143063\n",
      "epoch 18,loss:0.0020973801147192717\n",
      "epoch 20,loss:0.0008584497263655066\n",
      "epoch 22,loss:0.000351503404090181\n",
      "epoch 24,loss:0.0001439498009858653\n",
      "epoch 26,loss:5.896082075196318e-05\n",
      "epoch 28,loss:2.4150571334757842e-05\n",
      "epoch 30,loss:9.892976777337026e-06\n",
      "epoch 32,loss:4.051220457768068e-06\n",
      "epoch 34,loss:1.659877284510003e-06\n",
      "epoch 36,loss:6.803269911870302e-07\n",
      "epoch 38,loss:2.7873016961166286e-07\n",
      "epoch 40,loss:1.1437386149282247e-07\n",
      "epoch 42,loss:4.678759779608299e-08\n",
      "epoch 44,loss:1.9184653865522705e-08\n",
      "epoch 46,loss:7.8580342233181e-09\n",
      "epoch 48,loss:3.251223290590133e-09\n",
      "epoch 50,loss:1.3472529758473684e-09\n",
      "epoch 52,loss:5.544791292777518e-10\n",
      "epoch 54,loss:2.3217694433697034e-10\n",
      "epoch 56,loss:9.85451720225683e-11\n",
      "epoch 58,loss:4.177991286269389e-11\n",
      "epoch 60,loss:1.9248602711741114e-11\n",
      "epoch 62,loss:7.673861546209082e-12\n",
      "epoch 64,loss:3.410605131648481e-12\n",
      "epoch 66,loss:1.9610979506978765e-12\n",
      "epoch 68,loss:1.9610979506978765e-12\n",
      "epoch 70,loss:1.9610979506978765e-12\n",
      "epoch 72,loss:1.9610979506978765e-12\n",
      "epoch 74,loss:1.9610979506978765e-12\n",
      "epoch 76,loss:1.9610979506978765e-12\n",
      "epoch 78,loss:1.9610979506978765e-12\n",
      "epoch 80,loss:1.9610979506978765e-12\n",
      "epoch 82,loss:1.9610979506978765e-12\n",
      "epoch 84,loss:1.9610979506978765e-12\n",
      "epoch 86,loss:1.9610979506978765e-12\n",
      "epoch 88,loss:1.9610979506978765e-12\n",
      "epoch 90,loss:1.9610979506978765e-12\n",
      "epoch 92,loss:1.9610979506978765e-12\n",
      "epoch 94,loss:1.9610979506978765e-12\n",
      "epoch 96,loss:1.9610979506978765e-12\n",
      "epoch 98,loss:1.9610979506978765e-12\n",
      "epoch 100,loss:1.9610979506978765e-12\n"
     ]
    }
   ],
   "execution_count": 18
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-26T03:38:24.316563Z",
     "start_time": "2025-06-26T03:38:24.304438Z"
    }
   },
   "cell_type": "code",
   "source": "conv2d.weight.data.reshape((1, 2)) #可以看到很接近1",
   "id": "51242c678b8d083e",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[ 1.0027, -0.9812]])"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 17
  },
  {
   "metadata": {},
   "cell_type": "code",
   "outputs": [],
   "execution_count": null,
   "source": "",
   "id": "791fa715edd23f8c"
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
